package gybase02

/*
    函数与闭包
    闭包相当于代码块

   groovy 闭包的类型是 Closure


 */

def closure = {
        //代码块，和方法体一样
        // 1、默认接收一个参数, 这个参数可以直接使用 it
//    println it

//    -> //2、这个相当于无参数，不能使用it,不能再传入参数
//    println it

        //3、定义多个参数
//    a,b,c ->
//    println "a = $a ,b = $b, c = $c"
        //3、多个参数 支持默认初始值
    a = 7, b = 5, c ->
        println "a = $a ,b = $b, c = $c"

}

//closure(222)
//closure(4,5,6)
closure(6)
//a = 7 ,b = 5, c = 6
println closure.class
//class gybase02.GyBiBao$_run_closure1 动态生成，运行时生成  查看字节码 run方法里生成 class _run_closure1

//4、闭包可以作为方法的参数

//def func(closure){
//    closure()
//}

//func(){
//
//}

//func{//只有一个闭包参数
//        //这里是闭包执行的代码，相当于传入一个匿名函数
//        println "call"
//}

//Closure 查看源码里 执行 call
/*

interface Action {
    void call()
}

def funcc(closure) {
    closure()
}

def funcc2(Closure closure) {
    closure()
}

funcc(new Action() {
    @Override
    void call() {
        println "func Action  call"
    }
})
//func Action  call

*/


/*

Closure closure2 = new Action(){
    @Override
    void call() {
        println "Closure 强转 Actionfunc Action  call"
    }
} as Closure

funcc2(closure2)

*/

/*
    执行funcc2(closure2)报错如下：
    Cannot cast object 'gybase02.GyBiBao$2@6f330eb9' with class 'gybase02.GyBiBao$2' to class 'groovy.lang.Closure'

    不能将 Action 强转为 Closure

 */


/*
    类当中定义了一个call方法，可以直接使用对象()去调用call方法
 */
class Action{
    void call(){
        println"class call"
    }

    void call(a){
        println"class call  a = $a"
    }

    void test(){//这个方法不会被调用
        println"class test"
    }
}

new Action()()// 后面的（）相当于定义一个变量，然后调用 call方法
//class call

def a = new Action()
a()//调用 call方法
a(222)//调用 call方法
//class call
//class call  a = 222

/*
    package groovy.lang;
    Closure 类里 比较重要的成员变量

    private Object delegate;
    private Object owner;
    private Object thisObject;
    private int resolveStrategy = OWNER_FIRST;
    private int directive;
    protected Class[] parameterTypes;
    protected int maximumNumberOfParameters;

 */

def closure2 = {
    a2,b3 ->
        println a2.getClass()
        println b3.getClass()
}
closure2(1,2)
println closure2.parameterTypes //参数类型
println closure2.maximumNumberOfParameters//数组最大参数
/*
    class java.lang.Integer
    class java.lang.Integer
    [class java.lang.Object, class java.lang.Object]
    2
 */


def closure3 = {//这里可以获取到参数具体类型
    int a3,int b4 ->
        println a3.getClass()
        println b4.getClass()
}
closure3(1,2)
println closure3.parameterTypes //参数类型
println closure3.maximumNumberOfParameters//数组最大参数
/*
    class java.lang.Integer
    class java.lang.Integer
    [int, int]                  这里可以获取到参数具体类型，因为定义参数是明确指定出参数类型了
    2
 */

def closure4 = {
//    println " this is "+this
//    println " owner is "+owner
//    println " delegate is "+delegate

    println " this is $this"
    println " owner is $owner"
    println " delegate is $delegate"
}
closure4()
/*
     this is gybase02.GyBiBao@22175d4f
     owner is gybase02.GyBiBao@22175d4f
     delegate is gybase02.GyBiBao@22175d4f
 */


class Test {
  /*  def closure = {
//    println " this is "+this
//    println " owner is "+owner
//    println " delegate is "+delegate
        println " ----------- -------------------------------------"

        println "Test this is $this"
        println "Test owner is $owner"
        println "Test delegate is $delegate"

    }*/

/*

    static def closure2 = {
//    println " this is "+this
//    println " owner is "+owner
//    println " delegate is "+delegate
        println " ----------- -------------------------------------"

        println "Test this is $this"
        println "Test owner is $owner"
        println "Test delegate is $delegate"

    }
*/


    def closure3 = {
       def  closure4 = {
            println " ----------- -------------------------------------"

           //this 是 Test@66d57c1b
            println "closure4 this is "+this

           //owner 是 Test$_closure2@27494e46                定义它的时候的类的对象
           println "closure4 owner is "+owner

           //delegate 是Test$_closure2@27494e46              默认就是owner , 但是代理可以修改  //查看源码 Closure ,如下：
           /*
                 public V call(Object... args) {
                        try {
                            return (V) getMetaClass().invokeMethod(this,"doCall",args);
                        } catch (InvokerInvocationException e) {
                            UncheckedThrow.rethrow(e.getCause());
                            return null; // unreachable statement
                        }  catch (Exception e) {
                            return (V) throwRuntimeException(e);
                        }
                    }
            */
           println "closure4 delegate is "+delegate
        }
        closure4()

    }
}
//new Test().closure()
//Test this is gybase02.Test@5d52e3ef
//Test owner is gybase02.Test@5d52e3ef
//Test delegate is gybase02.Test@5d52e3ef

//new Test().closure2()
//Test this is class gybase02.Test
//Test owner is class gybase02.Test
//Test delegate is class gybase02.Test

new Test().closure3()
//closure4 this is gybase02.Test@66d57c1b               这里this就不一样了  this是Test类
//closure4 owner is gybase02.Test$_closure2@27494e46        _closure2@27494e46
//closure4 delegate is gybase02.Test$_closure2@27494e46     _closure2@27494e4



def funa(){
    println "执行 funa"
}

def closureA = {
    funa()
}
closureA()//这里可以直接调用 funa
//执行 funa

/*
    下面将 funb方法类里面，是不能直接调用的，需要通过代理 delegate 修改
    注意：调用 funb 跟 代理的策略有关 如果在外面 定义了 funb ，即使 delegate指定了类，还会调用 外面（脚本）的 funb

     代理的策略默认是owner
     private int resolveStrategy = OWNER_FIRST;
     public Closure(Object owner, Object thisObject) {
     this.owner = owner;
     this.delegate = owner;
     this.thisObject = thisObject;
 */
class Test2{
    def funb(){
        println "Test2 执行 funb"
    }
}

def funb(){
    println "Script 执行 funb"
}

def closureB = {
    funb()
}
closureB.delegate = new Test2()// 优先选择 owner
/*
    Closure.DELEGATE_FIRST
    Closure.DELEGATE_ONLY
    Closure.OWNER_ONLY
    Closure.TO_SELF
 */
closureB.resolveStrategy = Closure.DELEGATE_FIRST //执行 Test2 执行 funb
closureB()
//执行 funb
//Script 执行 funb




